package until;

import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.OkUrlFactory;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.*;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author 80119490
 */
public class HttpUtils {
	private static final Logger LOGGER = LoggerFactory.getLogger(HttpUtils.class);
	private static final Integer DEFAULT_CONNECTION_TIMEOUT = 10;
	private static final Integer DEFAULT_READ_TIMEOUT = 30;
	private static final Integer DEFAULT_WRITE_TIMEOUT = 30;
	private static OkUrlFactory factory;

	static {
		X509TrustManager trustManager = new X509TrustManager() {
			@Override
			public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
			}

			@Override
			public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
			}

			@Override
			public X509Certificate[] getAcceptedIssuers() {
				return new X509Certificate[0];
			}
		};
		SSLContext sslContext = null;
		try{
			sslContext  = SSLContext.getInstance("SSL");
			sslContext.init(null,new TrustManager[]{trustManager},new SecureRandom());
		}
		catch (Exception ex){
			LOGGER.error("build http ssl context error",ex);
		}
		HostnameVerifier hostnameVerifier = new HostnameVerifier() {
			@Override
			public boolean verify(String hostname, SSLSession session) {
				return true;
			}
		};


		OkHttpClient okHttpClient = new OkHttpClient();
		okHttpClient.setConnectTimeout(DEFAULT_CONNECTION_TIMEOUT, TimeUnit.SECONDS);
		okHttpClient.setReadTimeout(DEFAULT_READ_TIMEOUT, TimeUnit.SECONDS);
		okHttpClient.setWriteTimeout(DEFAULT_WRITE_TIMEOUT, TimeUnit.SECONDS);
		okHttpClient.setFollowRedirects(false);
		okHttpClient.setFollowSslRedirects(false);
		if(sslContext != null) {
			okHttpClient.setSslSocketFactory(sslContext.getSocketFactory());
		}
		okHttpClient.setHostnameVerifier(hostnameVerifier);

		factory = new OkUrlFactory(okHttpClient);
	}

	public static HttpURLConnection execute(String url, String method, Map<String, String> header, byte[] body, Integer connectionTimeout, Integer readTimeOut) {
		HttpURLConnection connection = null;
		try {
			if (!url.contains("http")) {
				url = "http://" + url;
			}
			connection = factory.open(new URL(url));
			connection.setRequestMethod(method.toUpperCase());
			if (connectionTimeout != null) {
				connection.setConnectTimeout(connectionTimeout);
			}
			if (readTimeOut != null) {
				connection.setReadTimeout(readTimeOut);
			}
			if (header != null) {
				header.putIfAbsent("Connection", "close");
				for (Map.Entry<String, String> entry : header.entrySet()) {
					connection.setRequestProperty( entry.getKey(),entry.getValue());
				}
			}
			if (body != null) {
				connection.setDoOutput(true);
				IOUtils.write(body, connection.getOutputStream());
			}
			return connection;
		} catch (Exception e) {
			if(connection != null){
				IOUtils.close(connection);
			}
			return null;
		}
	}

	public static byte[] fetch(String url,String method, Map<String,String> header,byte[] body,Integer connectionTimeout,Integer readTimeOut){
		HttpURLConnection connection = null;
		OutputStream outputStream = null;
		InputStream inputStream = null;
		try {
			if(!url.contains("http")){
				url = "http://"+url;
			}
			connection = factory.open(new URL(url));
			connection.setRequestMethod(method.toUpperCase());

			//连接超时
			if(connectionTimeout != null){
				connection.setConnectTimeout(connectionTimeout);
			}
			//读取超时
			if(readTimeOut != null){
				connection.setReadTimeout(readTimeOut);
			}

			if(header != null){
				//不维持连接
				header.putIfAbsent("Connection", "close");

				//填充header
				for(Map.Entry<String, String> entry : header.entrySet()){
					connection.setRequestProperty(entry.getKey(),entry.getValue());
				}
			}

			//传输body
			if(body != null){
				connection.setDoOutput(true);
				outputStream = connection.getOutputStream();
				IOUtils.write(body,outputStream);
			}

			inputStream = connection.getInputStream();
			return  IOUtils.toByteArray(inputStream);

		} catch (Exception e) {
			try {
				String errMsg = "";
				if(connection != null){
					if(connection.getErrorStream() != null) {
						errMsg = IOUtils.toString(connection.getErrorStream());
					}
					LOGGER.error("fetch http request data error,http code:{},error response:{}",connection.getResponseCode(),errMsg,e);
				}
			} catch (Exception e1) {
				LOGGER.error("get http response info error,",e1);
			}
		}
		finally {
			if(inputStream != null){
				IOUtils.closeQuietly(inputStream);
			}
			if(outputStream != null){
				IOUtils.closeQuietly(outputStream);
			}
			if(connection != null){
				IOUtils.close(connection);
			}
		}

		return null;
	}
}